package top.reminis.utils;

import lombok.extern.slf4j.Slf4j;
import top.reminis.conf.JobConfig;

import java.util.ArrayList;
import java.util.List;

/**
 * 配置验证工具类
 * 用于验证配置文件的完整性和正确性
 * 
 * @author zwf
 * @create 2025-09-25
 */
@Slf4j
public class ConfigValidator {

    /**
     * 验证作业配置的完整性
     */
    public static void validateJobConfig(JobConfig config) {
        List<String> errors = new ArrayList<>();
        
        // 验证基本信息
        if (config.getJobName() == null || config.getJobName().trim().isEmpty()) {
            errors.add("作业名称不能为空");
        }
        
        // 验证数据源配置
        if (config.getDataSources() == null || config.getDataSources().isEmpty()) {
            errors.add("至少需要配置一个数据源");
        } else {
            for (JobConfig.DataSourceConfig source : config.getDataSources()) {
                validateDataSourceConfig(source, errors);
            }
        }
        
        // 验证数据目标配置
        if (config.getDataSinks() == null || config.getDataSinks().isEmpty()) {
            errors.add("至少需要配置一个数据目标");
        } else {
            for (JobConfig.DataSinkConfig sink : config.getDataSinks()) {
                validateDataSinkConfig(sink, errors);
            }
        }
        
        // 验证数据流配置
        if (config.getDataFlows() == null || config.getDataFlows().isEmpty()) {
            errors.add("至少需要配置一个数据流");
        } else {
            for (JobConfig.DataFlowConfig flow : config.getDataFlows()) {
                validateDataFlowConfig(flow, errors);
            }
        }
        
        // 验证存储配置
        if (config.getStorage() == null) {
            errors.add("存储配置不能为空");
        } else {
            validateStorageConfig(config.getStorage(), errors);
        }
        
        // 验证Catalog配置
        if (config.getCatalogs() == null || config.getCatalogs().isEmpty()) {
            errors.add("至少需要配置一个Catalog");
        } else {
            for (JobConfig.CatalogConfig catalog : config.getCatalogs()) {
                validateCatalogConfig(catalog, errors);
            }
        }
        
        // 如果有错误，抛出异常
        if (!errors.isEmpty()) {
            StringBuilder errorMsg = new StringBuilder("配置验证失败:\n");
            for (String error : errors) {
                errorMsg.append("  - ").append(error).append("\n");
            }
            throw new IllegalStateException(errorMsg.toString());
        }
        
        log.info("配置验证通过，作业: {}", config.getJobName());
    }
    
    /**
     * 验证数据源配置
     */
    private static void validateDataSourceConfig(JobConfig.DataSourceConfig source, List<String> errors) {
        if (source.getName() == null || source.getName().trim().isEmpty()) {
            errors.add("数据源名称不能为空");
        }
        
        if (source.getType() == null || source.getType().trim().isEmpty()) {
            errors.add("数据源类型不能为空");
        }
        
        if ("kafka".equalsIgnoreCase(source.getType())) {
            if (source.getTopic() == null || source.getTopic().trim().isEmpty()) {
                errors.add("Kafka数据源必须配置topic");
            }
            if (source.getBootstrapServers() == null || source.getBootstrapServers().trim().isEmpty()) {
                errors.add("Kafka数据源必须配置bootstrap_servers");
            }
            if (source.getGroupId() == null || source.getGroupId().trim().isEmpty()) {
                errors.add("Kafka数据源必须配置group_id");
            }
        }
        
        if (source.getFields() == null || source.getFields().isEmpty()) {
            errors.add("数据源 " + source.getName() + " 缺少字段定义");
        }
    }
    
    /**
     * 验证数据目标配置
     */
    private static void validateDataSinkConfig(JobConfig.DataSinkConfig sink, List<String> errors) {
        if (sink.getName() == null || sink.getName().trim().isEmpty()) {
            errors.add("数据目标名称不能为空");
        }
        
        if (sink.getType() == null || sink.getType().trim().isEmpty()) {
            errors.add("数据目标类型不能为空");
        }
        
        if ("iceberg".equalsIgnoreCase(sink.getType())) {
            if (sink.getTableName() == null || sink.getTableName().trim().isEmpty()) {
                errors.add("Iceberg数据目标必须配置table_name");
            }
        }
        
        if ("kafka".equalsIgnoreCase(sink.getType())) {
            if (sink.getTopic() == null || sink.getTopic().trim().isEmpty()) {
                errors.add("Kafka数据目标必须配置topic");
            }
            if (sink.getBootstrapServers() == null || sink.getBootstrapServers().trim().isEmpty()) {
                errors.add("Kafka数据目标必须配置bootstrap_servers");
            }
        }
        
        if (sink.getFields() == null || sink.getFields().isEmpty()) {
            errors.add("数据目标 " + sink.getName() + " 缺少字段定义");
        }
    }
    
    /**
     * 验证数据流配置
     */
    private static void validateDataFlowConfig(JobConfig.DataFlowConfig flow, List<String> errors) {
        if (flow.getName() == null || flow.getName().trim().isEmpty()) {
            errors.add("数据流名称不能为空");
        }
        
        if (flow.getSourceTable() == null || flow.getSourceTable().trim().isEmpty()) {
            errors.add("数据流 " + flow.getName() + " 缺少源表配置");
        }
        
        if (flow.getTargetTable() == null || flow.getTargetTable().trim().isEmpty()) {
            errors.add("数据流 " + flow.getName() + " 缺少目标表配置");
        }
        
        if (flow.getFieldMappings() == null || flow.getFieldMappings().isEmpty()) {
            errors.add("数据流 " + flow.getName() + " 缺少字段映射配置");
        } else {
            for (JobConfig.FieldMapping mapping : flow.getFieldMappings()) {
                if (mapping.getSource() == null || mapping.getSource().trim().isEmpty()) {
                    errors.add("数据流 " + flow.getName() + " 的字段映射缺少源字段");
                }
                if (mapping.getTarget() == null || mapping.getTarget().trim().isEmpty()) {
                    errors.add("数据流 " + flow.getName() + " 的字段映射缺少目标字段");
                }
            }
        }
    }
    
    /**
     * 验证存储配置
     */
    private static void validateStorageConfig(JobConfig.StorageConfig storage, List<String> errors) {
        if (storage.getType() == null || storage.getType().trim().isEmpty()) {
            errors.add("存储类型不能为空");
        }
        
        if ("minio".equalsIgnoreCase(storage.getType()) || "s3".equalsIgnoreCase(storage.getType())) {
            if (storage.getEndpoint() == null || storage.getEndpoint().trim().isEmpty()) {
                errors.add("MinIO/S3存储必须配置endpoint");
            }
            if (storage.getAccessKey() == null || storage.getAccessKey().trim().isEmpty()) {
                errors.add("MinIO/S3存储必须配置access_key");
            }
            if (storage.getSecretKey() == null || storage.getSecretKey().trim().isEmpty()) {
                errors.add("MinIO/S3存储必须配置secret_key");
            }
            if (storage.getBucket() == null || storage.getBucket().trim().isEmpty()) {
                errors.add("MinIO/S3存储必须配置bucket");
            }
        }
    }
    
    /**
     * 验证Catalog配置
     */
    private static void validateCatalogConfig(JobConfig.CatalogConfig catalog, List<String> errors) {
        if (catalog.getName() == null || catalog.getName().trim().isEmpty()) {
            errors.add("Catalog名称不能为空");
        }
        
        if (catalog.getType() == null || catalog.getType().trim().isEmpty()) {
            errors.add("Catalog类型不能为空");
        }
        
        if ("iceberg".equalsIgnoreCase(catalog.getType())) {
            if (catalog.getUri() == null || catalog.getUri().trim().isEmpty()) {
                errors.add("Iceberg Catalog必须配置uri");
            }
            if (catalog.getUsername() == null || catalog.getUsername().trim().isEmpty()) {
                errors.add("Iceberg Catalog必须配置username");
            }
            if (catalog.getPassword() == null || catalog.getPassword().trim().isEmpty()) {
                errors.add("Iceberg Catalog必须配置password");
            }
            if (catalog.getWarehouse() == null || catalog.getWarehouse().trim().isEmpty()) {
                errors.add("Iceberg Catalog必须配置warehouse");
            }
        }
    }
}
